Skip to main content

第 14 章:把現有架構匯入狀態檔

當我們想把原有的基礎架構改成用 Terraform 控制時,可以使用 terraform import 指令,將現有的資源匯入 Terraform。

不同於從零開始使用 Terraform 的工作流程,匯入的過程大概會經過以下步驟:

  1. 找出要匯入的資源 id
  2. 匯入到 Terraform 狀態檔
  3. 修改 Terraform 組態檔以符合實際的基礎架構
  4. 執行 terraform plan 驗證組態檔的正確性

準備

我們以 AWS 的 EC2 instance 為測試案例,事先建立一台虛擬機 (可以使用前幾篇的範例來快速建立)。

找到 instance id: i-0123abcd

開始匯入

先建立 main.tf,加入 aws provider 的設定

provider "aws" {
profile = "default"
region = "ap-northeast-1"
}

執行 terraform init 初始化你的工作資料夾

$ terraform init

接著在 main.tf 加入空的 aws_instance resource 區塊

resource "aws_instance" "web" {}

執行 terraform import <resouce 名稱> <ID> 指令匯入

$ terraform import aws_instance.web i-042c5053c3ba5622e
aws_instance.web: Importing from ID "i-042c5053c3ba5622e"...
aws_instance.web: Import prepared!
Prepared aws_instance for import
aws_instance.web: Refreshing state... [id=i-042c5053c3ba5622e]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

成功之後,使用 terraform show 查看匯入的狀態

$ terraform show
# aws_instance.web:
resource "aws_instance" "web" {
ami = "ami-05484c96f4ac5493e"
...
vpc_security_group_ids = [
"sg-069828d4600dcef95",
"sg-07a788a7e5772455e",
]

credit_specification {
cpu_credits = "standard"
}

metadata_options {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "optional"
}

root_block_device {
delete_on_termination = true
device_name = "/dev/sda1"
encrypted = false
iops = 100
volume_id = "vol-06b89ae054f993045"
volume_size = 8
volume_type = "gp2"
}

timeouts {}
}

修改組態檔

匯入狀態之後,還要建立一個完整的組態檔,之後才有辦法用 Terraform 控制基礎架構。

首先執行 terraform plan,會看到錯誤訊息,提示缺少的設定。

$ terraform plan

Error: Missing required argument

on main.tf line 6, in resource "aws_instance" "web":
6: resource "aws_instance" "web" {}

The argument "instance_type" is required, but no definition was found.

Error: Missing required argument

on main.tf line 6, in resource "aws_instance" "web":
6: resource "aws_instance" "web" {}

The argument "ami" is required, but no definition was found.

我們依照錯誤訊息並參考狀態檔的內容,修改 aws_instance resource 區塊如下:

resource "aws_instance" "web" {
ami = "ami-05484c96f4ac5493e"
instance_type = "t2.micro"
}

再次執行 terraform plan,這次沒有錯誤了,不過還是有一些小狀況。

根據 plan 的結果,顯示組態檔跟實際的情況還是有差異。

$ terraform plan

...

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place

Terraform will perform the following actions:

# aws_instance.web will be updated in-place
~ resource "aws_instance" "web" {
ami = "ami-05484c96f4ac5493e"
...
id = "i-042c5053c3ba5622e"
instance_state = "running"
instance_type = "t2.micro"
...
~ tags = {
- "Name" = "web-packer-terraform" -> null
- "topic" = "web-packer" -> null
}
tenancy = "default"
volume_tags = {}
vpc_security_group_ids = [
"sg-069828d4600dcef95",
"sg-07a788a7e5772455e",
]

...
}

Plan: 0 to add, 1 to change, 0 to destroy.

我們根據差異的內容,修改組態檔如下:

provider "aws" {
profile = "default"
region = "ap-northeast-1"
}

resource "aws_instance" "web" {
ami = "ami-05484c96f4ac5493e"
instance_type = "t2.micro"

tags = {
"Name" = "web-packer-terraform"
"topic" = "web-packer"
}
}

再次執行 terraform plan,這次一模一樣了。

$ terraform plan

...

No changes. Infrastructure is up-to-date.